<html>

	<head>
		<title>DeviceOrientationEvent</title>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
		<!--<script src="util/jibu.js" type="text/javascript" charset="utf-8"></script>-->
		<style type="text/css">
			.www {
				width: 100px;
				height: 50px;
				text-align: center;
				line-height: 50px;
				font-size: 18px;
				background: green;
				color: #fff;
				margin: 100px auto;
			}
		</style>
	</head>

	<body>
		<h1>我的计步</h1> 
		<div id="fangxiang">

		</div>
		<div id="jiasudu3">

		</div>
		<div id="bushu">

		</div>
		<div id="jiasuji">

		</div>
	</body>

</html>

<script>
	var resultX = 31; //xy坐标
	var resultY = 13; //xy坐标
	FengZhuangXY();

	function FengZhuangXY() {

		//状态：静止
		var STAY = 0;
		//状态：运动
		var MOVE = 1;
		//运动状态判断数组，长度20
		var stateValue = new Array(20).fill(0);
		//加速度数组  长度100
		var Accs = new Array(100).fill(0);;
		//每次传入加速度的时间，省去定时器 长度100
		var time = new Array(100).fill(0);
		//数组下标
		var count = 0;
		//行走步数
		var Step = 0;
		//步长
		var Length = 0;

		//行进距离
		var Distance = 0;
		var RDistance = 0;
		//状态
		var State = STAY;;

		var Ldirection = ''; //浏览器方向
		var direction;

		var AccelerometerX, AccelerometerY, AccelerometerZ; //加速计三个方向的数据
		var count = 0;
		var responseObj = {};
		var wobushu;

		try {
			var text = "";
			window.addEventListener("deviceorientation", orientationHandler, false);

			function orientationHandler(event) {
				var jtext = ''
				var fangxiang = document.getElementById("fangxiang");
				jtext += "方向：" + event.alpha + "<p>";
				fangxiang.innerHTML = jtext;

				direction = Math.round(event.alpha)
				Ldirection = 360 - Math.round(event.alpha);
				Ldirection += 180; //地图的0度和获取的度数相反
				Ldirection += 3; //获取的度数和地图偏差角

				if(Ldirection >= 360) {
					Ldirection -= 360;
				}
			}
		} catch(e) {
			//		$("#arrow").html(e.message)
		}

		if(window.DeviceMotionEvent) {
			window.addEventListener('devicemotion', deviceMotionHandler, false);
		}
		var vibrateSupport = "vibrate" in navigator
		if(vibrateSupport) { //兼容不同的浏览器
			navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
		}

		function deviceMotionHandler(eventData) {
			var acceleration = eventData.accelerationIncludingGravity;
			AccelerometerX = acceleration.x;
			AccelerometerY = acceleration.y;
			AccelerometerZ = acceleration.z;
			
			var jtext = ''
			var jiasuji = document.getElementById("jiasuji");
			jtext += "AccelerometerX：" + AccelerometerX + "<p>";
			jtext += "AccelerometerY：" + AccelerometerY + "<p>";
			jtext += "AccelerometerZ：" + AccelerometerZ + "<p>";

			jiasuji.innerHTML = jtext;
			
			var currentTime = getCurrentTime();
			var valuesArray = [acceleration.x, acceleration.y, acceleration.z];
			refreshAcc(valuesArray, currentTime);

		}

		function refreshAcc(values, timestamp) {
			Accs[count] = Math.sqrt(values[0] * values[0] + values[1] * values[1] + values[2] * values[2]);
			time[count] = timestamp;
			//检查运动状态
			stateValue[count % 20] = Accs[count];
			checkState();
			//设置检测点，检测点的值为到最新数据的距离，如果太近了将无法确定其为波峰波谷
			//检测点的作用是来减少计算量
			var ckpoint = Accs.length / 5;
			//运动状态判断加上判断检测点是否有波谷存在
			if(State == MOVE && Accs[(count - ckpoint + Accs.length) % Accs.length] < Accs[(count - ckpoint + Accs.length + 1) % Accs.length] &&
				Accs[(count - ckpoint + Accs.length) % Accs.length] <
				Accs[(count - ckpoint + Accs.length - 1) % Accs.length]) {
				//求均值
				var ave0 = 0;
				for(var i = 0; i < Accs.length; ++i) {
					ave0 += Accs[i];
				}
				ave0 /= Accs.length;
				//调整数组顺序，把新数据放在前面，同时把数据减去均值

				var data = new Array(Accs.length).fill(0);
				for(var i1 = 0, j = count; i1 < data.length; ++i1, --j) {
					if(j < 0) {
						j += data.length
					};
					data[i1] = Accs[j] - ave0;
				}
				//寻找波峰波谷
				var sign = new Array(Accs.length).fill(0);
				for(var i2 = 1; i2 < Accs.length - 1; ++i2) {
					if(Math.abs(data[i2]) > 0.8 &&
						Math.abs(2 * data[i2]) > Math.abs((data[i2 - 1] + data[i2 + 1]))) {
						if(data[i2] > 0) {
							sign[i2] = 1;
						} else {
							sign[i2] = -1;
						}
					}
				}

				for(var i3 = 1; i3 < sign.length - 1;) {
					var idx = i3;
					while(++i3 < sign.length - 1 &&
						(sign[i3] == 0 || sign[i3] == sign[idx])) {
						if(sign[i3] != 0 && Math.abs(data[i3]) > Math.abs(data[idx])) {
							sign[idx] = 0;
							idx = i3;
						} else {
							sign[i3] = 0;
						}
					}
				}
				//再次判断检测点是否是波谷
				if(sign[ckpoint] < 0) {
					var index = ckpoint;
					//寻找下个波峰
					while(++index < sign.length && sign[index] == 0);
					if(index < sign.length && sign[index] > 0) {
						var peak = index;
						//寻找下个波谷
						while(++index < sign.length && sign[index] == 0);
						if(index < sign.length && sign[index] < 0) {
							var valley = index;
							//计算H和T
							var H = data[peak] - 0.5 * data[ckpoint] - 0.5 * data[valley];
							var T = time[(count - ckpoint + time.length) % time.length] - time[(count - valley + time.length) % time.length];

							//门限判决
							if(H > 3 && T > 300 && T < 1400) {
								// if (H > 2 && T > 300 && T < 1400) {
								//步长计算
								var steplength = 0.35 - 0.000155 * T + 0.1638 * Math.sqrt(H);
								Length = (Length + steplength) / 2;
								Distance += steplength;
								++Step;
								
								var jtext = ''
								var bushu = document.getElementById("bushu");
								jtext += "步数：" + Step + "<p>";
								bushu.innerHTML = jtext;
								console.log('Step', Step)
								suanXY(resultX, resultY, steplength, direction)
							}
						}
					}
				}
			}
			if(++count == 100) count = 0;

		}

		//检查运动状态
		function checkState() {
			var ave = 0;
			var Var = 0;
			//求均值
			for(var i = 0; i < stateValue.length; i++) {
				ave += stateValue[i];
			}
			ave /= stateValue.length;
			//求方差
			for(var i = 0; i < stateValue.length; i++) {
				Var += (stateValue[i] - ave) * (stateValue[i] - ave);
			}
			Var /= stateValue.length;
			//状态判决
			State = Var > 0.3 ? MOVE : STAY;
		}

		//获取当前时间戳
		function getCurrentTime() {
			var timestamp = new Date().getTime();
			return timestamp;
		}

		function suanXY(coordinateX, coordinateY, currentStepLength, cDirection) {
			resultX = parseFloat(coordinateX) + parseFloat(currentStepLength * Math.sin(Math.PI / 180 * cDirection));
			resultY = parseFloat(coordinateY) + parseFloat(currentStepLength * Math.cos(Math.PI / 180 * cDirection));
			var jtext = ''
			var jiasudu = document.getElementById("jiasudu3");
			jtext += "坐标x：" + resultX + "<p>";
			jtext += "坐标y：" + resultY + "<p>";

			jiasudu.innerHTML = jtext;

		}

	}
</script>